﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Room : MonoBehaviour {
	public Vector2 size;
	public List<GameObject> roomDoors = new List<GameObject>();
	public GameObject doorFiller;
	public List<GameObject> enemies = new List<GameObject>();
	public GameStateManager manager;
	public GameObject player;
	public bool roomCleared = false;
	public bool useDefaultSpawns = true;
	public GameObject defaultDrop;
	public bool secretRoom = false;
	bool dropped = false;
	List<GameObject> lights = new List<GameObject>();
	void Start() {
		manager = GameObject.Find("GameStateManager").GetComponent<GameStateManager>();
		if (secretRoom) {
			enemies.Clear ();
			Drop (manager.level + 2, new Vector3(-2,0,0), true);
			Drop (0, new Vector3(2,0,0), false, true);
			roomDoors[0].GetComponent<Door>().locked = true;
		}
		for (int i = 0; i < transform.childCount; i ++)
			if(transform.GetChild(i).tag == "RoomLight")
				lights.Add(transform.GetChild(i).gameObject);
		TurnLightsOff();
		player = GameObject.Find("Character");

		if (manager.level == 0 && name == "InitialRoom") {
			Drop (-1, new Vector3(-3,0,0), true);
			OpenDoors();
		}
	}
	void Update() {
		if (secretRoom && MiniGameManager.getInstance().inProgress) {
			if(MiniGameManager.getInstance().CheckGameOver()) {
				Debug.Log("Status: " + MiniGameManager.getInstance().finishStatus);
				MiniGameManager.getInstance().inProgress = false;
				if(MiniGameManager.getInstance().finishStatus == 1) {
					Debug.Log("Game is over and won");
					StartOpeningDoor();
				}
			} else {
				Debug.Log("Something else happened..." + MiniGameManager.getInstance().CheckGameOver() + ", " + MiniGameManager.getInstance().finishStatus);
			}
		} else if (secretRoom && roomDoors[0].GetComponent<Door>().locked) {
			if (Vector3.Distance (transform.position, player.transform.position) < 7) {
				if(Input.GetKeyUp(KeyCode.E) && manager.GetComponent<Inventory>().CheckKey()) {
					Connections.ServerManager.getInstance().minigameStart = true;
					if(!Connections.ServerManager.m_deviceConnected) {
						int level = UnityEngine.Random.Range(0, 512);
						Debug.Log ("Starting Mini Game with Level: " + level);
						MiniGameManager.getInstance().ChangeLevel(level);
					}
				}
			}
		}
		if (!roomCleared && enemies.Count == 0) {
			roomCleared = true;
			OpenDoors ();
			if (!dropped && name != "InitialRoom" && !secretRoom) {
				Drop (manager.level, new Vector3(-3,0,0), false);
				dropped = true;
				manager.roomsCleared++;
			}
		}
	}
	public void GetDoors(GameObject[,] doorObjects, LevelGeneration.doorState[,] doors) {
		for (int i = 0; i < size.x; i++) {
			for (int j = 0; j < size.y; j++) {
				int x = (int)WorldCoordsToArrayIndex(new Vector2(transform.localPosition.x + (float)i, transform.localPosition.y)).x;
				int y = (int)WorldCoordsToArrayIndex(new Vector2(transform.localPosition.x, transform.localPosition.y + (float)j)).y;
				if(doors[x,y] == LevelGeneration.doorState.DoorPlaced) {
					roomDoors.Add(doorObjects[x,y]);
				}
				else if(doors[x,y] == LevelGeneration.doorState.WallNeeded && j == 0) {
					GameObject tempFiller = (GameObject)GameObject.Instantiate(doorFiller);
					tempFiller.transform.parent = transform.parent;
					tempFiller.transform.localPosition = new Vector3(ArrayIndexToWorldCoords(x,y).x, ArrayIndexToWorldCoords(x,y).y,0);
					doors[x,y] = LevelGeneration.doorState.Filled;
				}
				else if(j != 0) {
					doors[x,y] = LevelGeneration.doorState.Interior;
				}
				y+= 1;
				if(doors[x,y] == LevelGeneration.doorState.DoorPlaced) {
					roomDoors.Add(doorObjects[x,y]);
				}
				else if(doors[x,y] == LevelGeneration.doorState.WallNeeded && i == 0) {
					GameObject tempFiller = (GameObject)GameObject.Instantiate(doorFiller);;
					tempFiller.transform.parent = transform.parent;
					tempFiller.transform.localPosition = new Vector3(ArrayIndexToWorldCoords(x,y).x, ArrayIndexToWorldCoords(x,y).y,0);
					tempFiller.transform.localRotation = Quaternion.Euler(0,0,90);
					doors[x,y] = LevelGeneration.doorState.Filled;
				}
				else if(i != 0) {
					doors[x,y] = LevelGeneration.doorState.Interior;
				}
				x+= 1;
				if(doors[x,y] == LevelGeneration.doorState.DoorPlaced) {
					roomDoors.Add(doorObjects[x,y]);
				}
				else if(doors[x,y] == LevelGeneration.doorState.WallNeeded && i == size.x - 1) {
					GameObject tempFiller = (GameObject)GameObject.Instantiate(doorFiller);;
					tempFiller.transform.parent = transform.parent;
					tempFiller.transform.localPosition = new Vector3(ArrayIndexToWorldCoords(x,y).x, ArrayIndexToWorldCoords(x,y).y,0);
					tempFiller.transform.localRotation = Quaternion.Euler(0,0,90);
					doors[x,y] = LevelGeneration.doorState.Filled;
				}
				else if(i != size.x -1) {
					doors[x,y] = LevelGeneration.doorState.Interior;
				}
				x-= 1;
				y+= 1;
				if(doors[x,y] == LevelGeneration.doorState.DoorPlaced) {
					roomDoors.Add(doorObjects[x,y]);
				}
				else if(doors[x,y] == LevelGeneration.doorState.WallNeeded && j == size.y - 1) {
					GameObject tempFiller = (GameObject)GameObject.Instantiate(doorFiller);;
					tempFiller.transform.parent = transform.parent;
					tempFiller.transform.localPosition = new Vector3(ArrayIndexToWorldCoords(x,y).x, ArrayIndexToWorldCoords(x,y).y,0);
					doors[x,y] = LevelGeneration.doorState.Filled;
				}
				else if(j != size.y - 1) {
					doors[x,y] = LevelGeneration.doorState.Interior;
				}
			}
		}
	}
	Vector2 WorldCoordsToArrayIndex(Vector2 position) {
			int x = (int)(position.x + 12 + (1-size.x)/2f);
			int y = (int)((position.y + 12 + (1-size.y)/2f) * 2);
			return new Vector2(x, y);
	}
	Vector2 ArrayIndexToWorldCoords(int x, int y) {
		float xtmp = x + ((y % 2 == 0) ? 0.5f : 0) - 12.5f;
		float ytmp = y * 0.5f - 12.5f;
		return new Vector2(xtmp, ytmp);
	}
	public void CloseDoors() {
		foreach(GameObject door in roomDoors){
			door.GetComponent<Door>().CloseDoor();
		}

	}
	public void UpdateEnemies() {
		foreach (GameObject enemy in enemies) {
			enemy.GetComponent<Enemy> ().UpdatePath ();
		}
	}
	public void OpenDoors() {
		foreach (GameObject door in roomDoors) {
			door.GetComponent<Door> ().OpenDoor ();
		}
	}
	public void TurnLightsOn() {
		foreach(GameObject light in lights) {
			light.GetComponent<Light>().enabled = true;
			light.SetActive(true);
		}
	}
	public void TurnLightsOff() {
		foreach(GameObject light in lights) {
			light.GetComponent<Light>().enabled = true;
			light.SetActive(false);
		}
	}
	void OnTriggerEnter(Collider other) {
		if(other.gameObject == player)
			manager.ChangeRoom(gameObject);
	}
	public void SpawnEnemies(int numToSpawn, List<GameObject> enemiesToSpawn) {
		manager = GameObject.Find("GameStateManager").GetComponent<GameStateManager>();
		if (useDefaultSpawns) {
			if (numToSpawn > (int)size.x * (int)size.y * 4)
				numToSpawn = (int)size.x * (int)size.y * 4;
			bool[,] spawnLoc = new bool[(int)size.x * 2, (int)size.y * 2];
			while (numToSpawn > 0) {
				int x, y;
				x = Random.Range(0, (int)size.x * 2);
				y = Random.Range(0, (int)size.y * 2);
				if(!spawnLoc[x,y]){
					spawnLoc[x,y] = true;
					numToSpawn--;
				}
			}
			for(int i = 0; i < (int)size.x * 2; i++) {
				for(int j = 0; j < (int)size.y * 2; j++) {
					if(spawnLoc[i,j]){
						GameObject tempEnemy = GameObject.Instantiate(enemiesToSpawn[Random.Range(0, enemiesToSpawn.Count)]);
						tempEnemy.transform.parent = transform.parent;
						tempEnemy.transform.localPosition = transform.localPosition + new Vector3(-.25f - (size.x - 1) * .5f + (float)i * .5f, -.25f - (size.y - 1) * .5f + (float)j * .5f, -.2f);
						tempEnemy.transform.localScale = new Vector3(.05f, .05f, .05f);
						enemies.Add(tempEnemy);
						tempEnemy.GetComponent<Enemy>().parentRoom = gameObject;
						tempEnemy.GetComponent<NavMeshAgent>().speed = 7 * ((manager.level + 5)/5f);
						tempEnemy.GetComponent<NavMeshAgent>().angularSpeed = 120 * ((manager.level + 5)/5f);
						tempEnemy.SetActive(false);
					}
				}
			}
		}
	}
	public void EnableEnemies(){
		foreach (GameObject enemy in enemies) enemy.SetActive(true);
	}
	void Drop(int quality, Vector3 spawnOffset, bool forceWeapon = false, bool forceHealth = false) {
		int random = Random.Range (0, 100);
		GameObject pickup = GameObject.Instantiate (defaultDrop);
		pickup.transform.position = transform.position + spawnOffset;
		if ((random < 35 && !forceWeapon) || forceHealth) { 
			pickup.GetComponent<Pickup>().SetupPickup("Health", (forceHealth)? 40:15);
		}
		else if ((random < 50 && !forceWeapon)) { 
			pickup.GetComponent<Pickup>().SetupPickup("Key", 0);
			Debug.Log("added key");
		}
		else if(random < 78 || forceWeapon) { 
			Inventory.InventoryItem item;
			item.fireMode = (Weapon.WeaponType)Random.Range (0, 4);
			item.type = "Weapon";
			item.damage = Random.Range(25f, 45f) * ((quality+6)/6f);
			item.accuracy = Random.Range(35f, 55f) * ((quality+6)/6f);
			item.fireRate = Random.Range(200f, 350f) * ((quality+6)/6f);
			item.clipSize = (int)(Random.Range(5f, 15f) * ((quality+10)/10f));
			item.reloadTime = Random.Range(3f, 6f) / ((9 + quality)/6f);
			switch(item.fireMode){
			case Weapon.WeaponType.Shotgun:
				item.fireRate *= 0.2f;
				item.damage *= 0.65f;
				item.accuracy *= 0.4f;
				item.clipSize = (int)(item.clipSize * 0.5f);
				break;
			case Weapon.WeaponType.Semi:
				item.fireRate *= 0.4f;
				item.damage *= 1.4f;
				item.clipSize = (int)(item.clipSize * 0.8f);
				break;
			case Weapon.WeaponType.Laser:
				item.damage *= 0.65f;
				break;
			case Weapon.WeaponType.Auto:
				item.clipSize *=2;
				break;
			}
			pickup.GetComponent<Pickup>().SetupPickup("Item", 0, item);
		}
		else {
			Inventory.InventoryItem item = new Inventory.InventoryItem();;
			item.type = "Armour";
			item.damage = Random.Range(12f, 27f) * (manager.level+5)/5f;
			pickup.GetComponent<Pickup>().SetupPickup("Item", 0, item);
		}

	}

	public void StartOpeningDoor() {
		Debug.Log ("Opening Doors - " + roomDoors.Count);
		roomDoors[0].GetComponent<Door>().locked = false;
		manager.secretsRooms++;
		OpenDoors();
	}
}
